﻿
Imports System.IO
Imports std

Public MustInherit Class mergedStaticRequest
    Inherits staticrequest

    'handle /***?a&b&c or /***?a.suffix&b.suffix&c.suffix
    'return the combine of a,b,c with filename a+b+c.css or a+b+c_c.css <crunched>
    'need to confirm there is not an existing static file has the name same as combine of some files
    'such as there should be a file named a+b+c.css, otherwise, it will be overwritten
    'we should only merge files with same suffix <is this true? but we can handle this kind of cases>

    Public Const fileseparator As Char = character.plusSign
#If RETIRED Then
    Public Shadows Const _pathidentity As String = "/ms/"
#End If
    Protected MustOverride Function suffix() As String

#If RETIRED Then
    Public Overrides Function pathidentity() As String
        Return _pathidentity
    End Function
#End If

    Protected Function barefilename(ByVal filename As String) As String
        If strendwith(filename, suffix, False) Then
            Return strleft(filename, strlen(filename) - strlen(suffix()))
        Else
            Return filename
        End If
    End Function

    Protected Overridable Shadows Function filefullpath(ByVal filename As String) As String
        If Not strcont(filename, suffix(), False) Then
            filename += suffix()
        End If
        Return staticrequest.filefullpath(filename)
    End Function

    'input an existing filename without path, and output a filename also without path
    Protected MustOverride Function finalhandle(ByVal src As String) As String

    Private Function merge(ByVal srcs As vector(Of String)) As String
        'do not generate useless files, so just crunch the dest if enabled
        'always merge here, cacheProcessor will handle cache

        If srcs Is Nothing OrElse srcs.size() = 0 Then
            Return Nothing
        ElseIf srcs.size() = 1 Then
            'need no merge here
            Return finalhandle(srcs(0))
        Else
            Dim dest As String = Nothing
            dest = combinefilename(srcs)

            'manully merge files, to avoid a dirty cmd /c copy /b .\static\... ... ...
            Dim writer As FileStream = Nothing
            Try
                writer = New FileStream(filefullpath(dest), FileMode.Create)
            Catch ex As Exception
                'only warning here, a special hacked url can make an invalid filename
                raiseError("cannot create writer for file " + filefullpath(dest) + ", ignore request.", _
                           errorHandle.errorType.warning)
                Return Nothing
            End Try
            Dim i As Int64
            For i = 0 To srcs.size() - 1
                Dim bytes() As Byte = Nothing
                Try
                    bytes = File.ReadAllBytes(filefullpath(srcs(i)))
                Catch ex As Exception
                    'only warning here, same as the one in writer
                    raiseError("cannot read file " + filefullpath(srcs(i)), errorHandle.errorType.warning)
                End Try
                If Not bytes Is Nothing Then
                    writer.Write(bytes, 0, bytes.Length())
                End If
            Next
            closestream(writer)

            Return finalhandle(dest)
        End If
    End Function

    Private Function combinefilename(ByVal srcs As vector(Of String)) As String
        If srcs Is Nothing OrElse srcs.size() = 0 Then
            Return Nothing
        Else
            Dim rtn As String = Nothing
            rtn = srcs(0)
            Dim i As Int64
            For i = 1 To srcs.size() - 1
                rtn += character.plusSign + barefilename(srcs(i))
            Next
            Return rtn
        End If
    End Function

    Protected Overridable Function validfilename(ByVal filename As String) As Boolean
        Return True
    End Function

    Protected NotOverridable Overrides Function filename(ByVal context As httpContext) As String
        Dim files As vector(Of String) = Nothing
        files = New vector(Of String)()
        Dim rawfiles As vector(Of String) = Nothing
        rawfiles = New vector(Of String)()
        strsepar(MyBase.filename(context), fileseparator, rawfiles)
        If Not rawfiles Is Nothing AndAlso rawfiles.size() > 0 Then
            Dim i As Int64
            For i = 0 To rawfiles.size() - 1
                Dim decodedfile As String = Nothing
                decodedfile = urlUtils.urldecode(rawfiles(i))
                If validfilename(decodedfile) Then
                    files.push_back(decodedfile)
                Else
                    'not valid, then ignore it
                    debugassert(False, "should not have a file not valid, " + decodedfile)
                End If
            Next
        End If
        Return merge(files)
    End Function

    'hiden the generateStaticfileLinkUrl in staticrequest
    Public Shared Shadows Function generateStaticfileLinkUrl(ByVal filename As String) As String
        debugassert(False, "should not call here.")
        Return Nothing
    End Function

    Protected Shared Function generateMergedStaticfileLinkUrl(ByVal pathidentity As String, _
                                                              ByVal ParamArray files() As String) As String
        Dim baseurl As String = Nothing
        baseurl = strmid(pathidentity, strlen(network.pathSeperator))
        If files Is Nothing OrElse files.Length() = 0 Then
            Return baseurl
        End If
        baseurl += urlUtils.urlencode(files(0))
        Dim i As Int64
        For i = 1 To files.Length() - 1
            baseurl += fileseparator + urlUtils.urlencode(files(i))
        Next

        Return baseurl
    End Function

    Public Shared Function generateMergedStaticfileLinkUrl(ByVal ParamArray files() As String) As String
        Return generateMergedStaticfileLinkUrl(_pathidentity, files)
    End Function
End Class
